home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / GXEdit Library & Doc / GXEditStyle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-10  |  22.2 KB  |  922 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:                GXEditStyle.c
  3.     
  4.     Contains:
  5.     
  6.     Written by:        Barton R. House
  7.     
  8.     Copyright:        © 1993 by Apple Computer, Inc., All rights reserved.
  9.     
  10. */
  11.  
  12. #include <Script.h>
  13.  
  14. #include "GXEdit.h"
  15. #include "GXEditDoc.h"
  16. #include "GXEditStyle.h"
  17. #include "GXEditDebug.h"
  18. #include "GXEditError.h"
  19. #include "GXEditUtils.h"
  20.  
  21. #include "math routines.h"
  22. #include "graphics routines.h"
  23. #include "graphics toolbox.h"
  24. #include "graphics libraries.h"
  25. #include "font routines.h"
  26. #include "layout routines.h"
  27. #include "layout types.h"
  28. #include "font menu library.h"
  29.  
  30. void IncrementDocStyleRefCount(DocPtr dp, short styleIndex)
  31. {
  32.     StylePtr    sp;
  33.     
  34.     sp = GetDocStyle(dp, styleIndex);
  35.     
  36.     sp->refCount++;
  37. }
  38.  
  39. void DecrementDocStyleRefCount(DocPtr dp, short styleIndex)
  40. {
  41.     StylePtr    sp;
  42.     
  43.     sp = GetDocStyle(dp, styleIndex);
  44.     
  45.     if(sp->refCount > 0)
  46.         sp->refCount--;
  47.     else
  48.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  49.     
  50. }
  51.  
  52. StylePtr GetDocStyle(DocPtr dp, short styleIndex)
  53. {
  54.     if(styleIndex < 0 || styleIndex > dp->numStyles)
  55.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  56.         
  57.     return(&(*dp->styles)[styleIndex]);
  58. }
  59.  
  60. short FindDocStyle(DocPtr dp, StylePtr matchSp)
  61. {
  62.     short        styleIndex;
  63.     StylePtr    sp;
  64.     
  65.     sp = *dp->styles;
  66.     
  67.     for(styleIndex = 0; styleIndex < dp->numStyles; styleIndex++, sp++)
  68.         if(matchSp->textFont == sp->textFont &&
  69.            matchSp->textSize == sp->textSize &&
  70.            GXEqualStyle(matchSp->textStyle, sp->textStyle))
  71.             return(styleIndex);
  72.     
  73.     return(-1);
  74.     
  75. }
  76.  
  77. void InitDocStyle(gxStyle textStyle, StylePtr newStyle)
  78. {
  79.     
  80.     newStyle->textStyle = GXCopyToStyle(nil, textStyle);
  81.     
  82.     newStyle->textSize = FixedToInt(GXGetStyleTextSize(newStyle->textStyle));
  83.     newStyle->textFont = GXGetStyleFont(newStyle->textStyle);
  84.         
  85.     newStyle->platform = GXGetStyleEncoding(newStyle->textStyle, &newStyle->script, &newStyle->language);
  86.     
  87.     newStyle->refCount = 0;
  88.     
  89. }
  90.  
  91. short AddDocTextStyle(DocPtr dp, gxStyle textStyle)
  92. {
  93.     StyleRec            newStyle;
  94.     StylePtr            sp;
  95.     short            i;
  96.     
  97.     InitDocStyle(textStyle, &newStyle);
  98.     
  99.     /* try to find a style that is unreferenced -- if none found, then add it */
  100.     
  101.     sp = *dp->styles;
  102.     
  103.     for(i=0; i<dp->numStyles; i++, sp++)
  104.         if(sp->refCount == 0) {
  105.             GXDisposeStyle(sp->textStyle);
  106.             BlockMove((Ptr) &newStyle, (Ptr) sp, sizeof(StyleRec));
  107.             return(i);
  108.         }
  109.         
  110.     PtrAndHand((Ptr) &newStyle, (Handle) dp->styles, sizeof(StyleRec));
  111.     
  112.     return(dp->numStyles++);
  113.  
  114. }
  115.  
  116. short SetDocStyleTextFont(DocPtr dp, short styleIndex, gxFont fontId)
  117. {
  118.     StyleRec    newStyle;
  119.     long        encodeIndex;
  120.     
  121.     newStyle = *GetDocStyle(dp, styleIndex);
  122.     
  123.     if(newStyle.textFont == fontId)
  124.         return(styleIndex);
  125.      
  126.     newStyle.textStyle = GXCopyToStyle(nil, newStyle.textStyle);
  127.     
  128.     /* lets make sure the new gxFont supports the gxStyle's script/language.
  129.          We don't have to di this if the platform is gxGlyphPlatform (script and language are meaningless)
  130.      */
  131.     
  132.     if(newStyle.platform != gxGlyphPlatform && GXFindFontEncoding(fontId, newStyle.platform, newStyle.script, newStyle.language) == 0) {
  133.     
  134.         /* let's try one more time, this time ignoring language */
  135.         /* NOTE: this is a tempoary hack until we figure out what the right thing to do is */
  136.         
  137.         if(GXFindFontEncoding(fontId, newStyle.platform,  newStyle.script,  gxNoLanguage) == 0) {
  138.     
  139.             /* oh no, we got to do something.  Lets just change to the first script/language that is supported */
  140.             
  141.             encodeIndex = GXFindFontEncoding(fontId, gxMacintoshPlatform, gxNoScript,  gxNoLanguage);
  142.             
  143.             GXGetFontEncoding(fontId, encodeIndex, &newStyle.script, &newStyle.language);
  144.             
  145.             GXSetStyleEncoding(newStyle.textStyle, gxMacintoshPlatform, newStyle.script, newStyle.language);
  146.             
  147.             newStyle.platform = gxMacintoshPlatform;
  148.         
  149.         }
  150.         
  151.     }    
  152.     
  153.     GXSetStyleFont(newStyle.textStyle, fontId);
  154.     newStyle.textFont = fontId;
  155.     
  156.     styleIndex = FindDocStyle(dp, &newStyle);
  157.     
  158.     if(styleIndex == -1)
  159.         styleIndex = AddDocTextStyle(dp, newStyle.textStyle);
  160.         
  161.     GXDisposeStyle(newStyle.textStyle);
  162.     
  163.     return(styleIndex);
  164.  
  165. }
  166.  
  167. gxFont GetDocStyleTextFont(DocPtr dp, short styleIndex)
  168. {
  169.     StylePtr        sp;
  170.     
  171.     if(styleIndex < 0 || styleIndex >= dp->numStyles)
  172.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  173.         
  174.     sp = *dp->styles + styleIndex;
  175.     
  176.     return(sp->textFont);
  177. }
  178.  
  179. short SetDocStyleTextSize(DocPtr dp, short styleIndex, short size)
  180. {
  181.     StyleRec    newStyle;
  182.     
  183.     newStyle = *GetDocStyle(dp, styleIndex);
  184.     
  185.     if(newStyle.textSize == size)
  186.         return(styleIndex);
  187.      
  188.     newStyle.textStyle = GXCopyToStyle(nil, newStyle.textStyle);
  189.     
  190.     GXSetStyleTextSize(newStyle.textStyle, ff(size));
  191.     
  192.     styleIndex = FindDocStyle(dp, &newStyle);
  193.     
  194.     if(styleIndex == -1)
  195.         styleIndex = AddDocTextStyle(dp, newStyle.textStyle);
  196.         
  197.     GXDisposeStyle(newStyle.textStyle);
  198.     
  199.     return(styleIndex);
  200.  
  201. }
  202.  
  203. short GetDocStyleTextSize(DocPtr dp, short styleIndex)
  204. {
  205.     StylePtr        sp;
  206.     
  207.     if(styleIndex < 0 || styleIndex >= dp->numStyles)
  208.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  209.         
  210.     sp = *dp->styles + styleIndex;
  211.     
  212.     return(sp->textSize);
  213. }
  214.  
  215. short SetDocStyleFeatures(DocPtr dp, short styleIndex, short numFeatures, gxRunFeature * features)
  216. {
  217.     StyleRec    newStyle;
  218.     
  219.     newStyle = *GetDocStyle(dp, styleIndex);
  220.     
  221.     newStyle.textStyle = GXCopyToStyle(nil, newStyle.textStyle);    
  222.     
  223.     GXSetStyleRunFeatures(newStyle.textStyle, numFeatures, (gxRunFeature *) features);
  224.     
  225.     styleIndex = FindDocStyle(dp, &newStyle);
  226.     
  227.     if(styleIndex == -1)
  228.         styleIndex = AddDocTextStyle(dp, newStyle.textStyle);        
  229.         
  230.     GXDisposeStyle(newStyle.textStyle);
  231.         
  232.     return(styleIndex);    
  233. }
  234.  
  235. short SetDocStyleEncoding(DocPtr dp, short styleIndex, gxFontPlatform platform, gxFontScript script, gxFontLanguage language)
  236. {
  237.     StyleRec        newStyle;
  238.     long            qdAppFont;
  239.     gxFont        appFont;
  240.     
  241.     newStyle = *GetDocStyle(dp, styleIndex);
  242.     
  243.     if(newStyle.platform == platform && newStyle.script == script && newStyle.language == language)
  244.         return(styleIndex);
  245.         
  246.     /* first lets make sure the gxStyle's gxFont supports the script/encoding */
  247.     
  248.     appFont = newStyle.textFont;
  249.  
  250.     if(platform != gxGlyphPlatform )
  251.         if(GXFindFontEncoding(newStyle.textFont, platform, script, language) == 0) {
  252.         
  253.             if(newStyle.platform == platform && newStyle.script == script && newStyle.language == gxNoLanguage)
  254.                 return(styleIndex);
  255.         
  256.             appFont = nil;
  257.                     
  258.             /* let's try one more time, this time ignoring language */
  259.             /* NOTE: this is a tempoary hack until we figure out what the right thing to do is */
  260.             
  261.             if(language != gxNoLanguage)
  262.                 if(GXFindFontEncoding(newStyle.textFont, platform, script, gxNoLanguage) != 0) {
  263.                     appFont = newStyle.textFont;
  264.                     language = gxNoLanguage;
  265.                 }
  266.         
  267.             /* Lets try to switch to the script's default gxFont */
  268.             
  269.             if(appFont == nil && (qdAppFont = GetScript((short) (script - 1), smScriptAppFond)) != 0)
  270.             {    gxStyle tmp = GXNewStyle();
  271.                 GXConvertQDFont(tmp, qdAppFont, 0);
  272.                 appFont = GXGetStyleFont(tmp);
  273.                 GXDisposeStyle(tmp);
  274.             }
  275.     
  276.             /* if that didn't work, lets try to find a gxFont that has this scrip/language encoding */
  277.             
  278.             if(appFont == nil)
  279.                 GXFindFonts(nil, gxNoFontName, platform, script, language, 0, nil, 1, 1, &appFont);
  280.                 
  281.             if(appFont == nil)
  282.                 if(GXFindFonts(nil, gxNoFontName, platform, script,  gxNoLanguage,0,  nil, 1, 1, &appFont) != 0)
  283.                     language =  gxNoLanguage;
  284.                 
  285.             /* if that didn't work -- something is really wrong */
  286.             
  287.             if(appFont == nil)
  288.                 gxEditPostError(dp, gx_edit_internal_fatal_error);
  289.     
  290.         }
  291.         
  292.     newStyle.textStyle = GXCopyToStyle(nil, newStyle.textStyle);    
  293.     
  294.     if(appFont != newStyle.textFont)
  295.         GXSetStyleFont(newStyle.textStyle, appFont);
  296.  
  297.     GXSetStyleEncoding(newStyle.textStyle, platform, script, language);
  298.     
  299.     styleIndex = FindDocStyle(dp, &newStyle);
  300.     
  301.     if(styleIndex == -1)
  302.         styleIndex = AddDocTextStyle(dp, newStyle.textStyle);        
  303.         
  304.     GXDisposeStyle(newStyle.textStyle);
  305.         
  306.     return(styleIndex);    
  307. }
  308.  
  309. void GetDocStyleFeatures(DocPtr dp, short styleIndex, short * numFeatures, gxRunFeature * features)
  310. {
  311.     StylePtr        sp;
  312.     long            num;
  313.     
  314.     if(styleIndex < 0 || styleIndex >= dp->numStyles)
  315.         gxEditPostError(dp, gx_edit_internal_fatal_error);
  316.         
  317.     sp = *dp->styles + styleIndex;
  318.     
  319.     num = GXGetStyleRunFeatures(sp->textStyle, (gxRunFeature *) features);
  320.     
  321.     if(numFeatures != nil)
  322.         *numFeatures = num;
  323.     
  324. }
  325.  
  326. void ModifyStyleFeatures(DocPtr dp, gxFont fontId, short numFeatureGroups,
  327.             short * srcFeatureGroupSizes,
  328.             gxRunFeature ** srcFeatureGroups,
  329.             short * dstFeatureGroupSizes,
  330.             gxRunFeature ** dstFeatureGroups,
  331.             short numStyles, short * oldStyles, short * newStyles)
  332. {
  333.     short                i, j, k, l;
  334.     short                numFeatures;
  335.     gxRunFeature        * features;
  336.     
  337.     if(numStyles == 0)
  338.         return;
  339.         
  340.     /* now loop through all of the given styles */
  341.  
  342.     for(i = 0; i < numStyles; i++, oldStyles++, newStyles++) {
  343.     
  344.         *newStyles = *oldStyles;        /* in case we don't match */
  345.     
  346.         if(GetDocStyleTextFont(dp, *oldStyles) == fontId) {
  347.             
  348.             GetDocStyleFeatures(dp, *oldStyles, &numFeatures, nil);
  349.             
  350.             features = (gxRunFeature *) NewPtr(sizeof(gxRunFeature) * numFeatures);
  351.             
  352.             GetDocStyleFeatures(dp, *oldStyles, nil, features);
  353.             
  354.             /* find feature group that matches */
  355.             
  356.             for(j=0; j<numFeatureGroups; j++) {
  357.                 
  358.                 if(srcFeatureGroupSizes[j] != numFeatures)
  359.                     continue;
  360.             
  361.                 for(k=0; k<numFeatures; k++) {
  362.                 
  363.                     for(l=0; l<numFeatures; l++)
  364.                         if((srcFeatureGroups[j])[k].featureType == features[l].featureType &&
  365.                            (srcFeatureGroups[j])[k].featureSelector == features[l].featureSelector)
  366.                             break;
  367.                             
  368.                     if(l == numFeatures)
  369.                         break;
  370.                 
  371.                 }
  372.                 
  373.                 if(k == numFeatures)
  374.                     break;
  375.             }
  376.             
  377.             if(j != numFeatureGroups)
  378.                 *newStyles = SetDocStyleFeatures(dp, *oldStyles,
  379.                                         dstFeatureGroupSizes[j], dstFeatureGroups[j]);
  380.                                         
  381.             DisposePtr((Ptr) features);
  382.                 
  383.         }
  384.                                     
  385.         /* increment the reference count temporarily so that the new style does not get wiped out
  386.              if another new style is created */
  387.              
  388.         IncrementDocStyleRefCount(dp, *newStyles);
  389.                                     
  390.     }
  391.     
  392.     /* decrement the reference counts */
  393.  
  394.     newStyles -= numStyles;    
  395.     for(i=0; i< numStyles; i++, newStyles++)
  396.         DecrementDocStyleRefCount(dp, *newStyles);
  397.     
  398. }
  399.  
  400. void ModifyStyleVariations(DocPtr dp, gxFont fontId, short numVariations, gxFontVariation * variations,
  401.                                 short numStyles, short * oldStyles, short * newStyles)
  402. {
  403.     StyleRec            newStyle;
  404.     short                i,j,k;
  405.     short                numFontVariations;
  406.     gxFontVariation        ** newVariations;
  407.     gxFontVariation        * vp;
  408.     gxFontVariation        * np;
  409.     
  410.     if(numStyles == 0)
  411.         return;
  412.         
  413.     /* now loop through all of the given styles */
  414.  
  415.     for(i = 0; i < numStyles; i++, oldStyles++, newStyles++) {
  416.     
  417.         *newStyles = *oldStyles;        /* in case we dont match */
  418.     
  419.         /* get the soon to be old variations */
  420.     
  421.         newStyle = *GetDocStyle(dp, *oldStyles);
  422.         
  423.         if(newStyle.textFont == fontId) {
  424.      
  425.             newStyle.textStyle = GXCopyToStyle(nil,newStyle.textStyle);
  426.             
  427.             numFontVariations = GXGetStyleFontVariations(newStyle.textStyle, nil);
  428.             newVariations = (gxFontVariation **) NewHandle(sizeof(gxFontVariation) * numFontVariations);
  429.             
  430.             HLock((Handle) newVariations);
  431.             
  432.             GXGetStyleFontVariations(newStyle.textStyle, *newVariations);
  433.             
  434.             vp = variations;
  435.             
  436.             for(j=0; j<numVariations; j++, vp++) {
  437.             
  438.                 np = *newVariations;
  439.                 
  440.                 for(k=0; k<numFontVariations; k++, np++)
  441.                     if(np->name == vp->name) {
  442.                         np->value = vp->value;
  443.                         break;
  444.                     }
  445.                     
  446.                 if(k == numFontVariations) {
  447.                 
  448.                     /* we need to add it */
  449.                     
  450.                     HUnlock((Handle) newVariations);
  451.                     
  452.                     numFontVariations++;
  453.                     SetHandleSize((Handle) newVariations, sizeof(gxFontVariation) * numFontVariations);
  454.                     
  455.                     HLock((Handle) newVariations);
  456.                     
  457.                     (*newVariations)[numFontVariations-1] = *vp;
  458.                     
  459.                 }
  460.                     
  461.             }
  462.             
  463. #ifdef debugging
  464.             GXIgnoreGraphicsNotice(font_variations_already_set);
  465. #endif
  466.             
  467.             GXSetStyleFontVariations(newStyle.textStyle, numFontVariations, *newVariations);
  468.             
  469. #ifdef debugging
  470.             GXPopGraphicsNotice();
  471. #endif
  472.             
  473.             *newStyles = FindDocStyle(dp, &newStyle);
  474.             
  475.             if(*newStyles == -1)
  476.                 *newStyles = AddDocTextStyle(dp, newStyle.textStyle);
  477.                 
  478.             HUnlock((Handle) newVariations);
  479.             
  480.             GXDisposeStyle(newStyle.textStyle);
  481.             DisposeHandle((Handle) newVariations);
  482.             
  483.         }
  484.         
  485.         /* increment the reference count temporarily so that the new style does not get wiped out
  486.              if another new style is created */
  487.              
  488.         IncrementDocStyleRefCount(dp, *newStyles);
  489.                                     
  490.     }
  491.     
  492.     /* decrement the reference counts */
  493.  
  494.     newStyles -= numStyles;    
  495.     for(i=0; i< numStyles; i++, newStyles++)
  496.         DecrementDocStyleRefCount(dp, *newStyles);
  497.     
  498. }
  499.  
  500. void ModifyStyleRunControls(DocPtr dp, gxRunControls * newRunControls, gxRunControls * runControlsMask,
  501.                                 short numStyles, short * oldStyles, short * newStyles)
  502. {
  503.     gxRunControls        runControls;
  504.     StyleRec            newStyle;
  505.     short            i;
  506.     char                * dst;
  507.     long                size;
  508.     
  509.     if(numStyles == 0)
  510.         return;
  511.         
  512.     /* now loop through all of the given styles */
  513.  
  514.     for(i = 0; i < numStyles; i++, oldStyles++, newStyles++) {
  515.     
  516.         *newStyles = *oldStyles;        /* in case we don't match */
  517.     
  518.         /* get the soon to be old run features */
  519.     
  520.         newStyle = *GetDocStyle(dp, *oldStyles);
  521.         
  522.         newStyle.textStyle = GXCopyToStyle(nil, newStyle.textStyle);
  523.         
  524.         if(!GXGetStyleRunControls(newStyle.textStyle, &runControls)) {
  525.         
  526.             /* initialize gxStyle run control to default values -- all zeros */
  527.  
  528.             size = sizeof(runControls);
  529.             dst = (char *) &runControls;
  530.             
  531.             while(size--)
  532.                 *dst++ = 0;
  533.             
  534.         }
  535.         
  536.         if(gxEditSetBitMaskOp(newRunControls, &runControls, runControlsMask, sizeof(runControls))) {
  537.                         
  538.             GXSetStyleRunControls(newStyle.textStyle, &runControls);
  539.             
  540.             *newStyles = FindDocStyle(dp, &newStyle);
  541.             
  542.             if(*newStyles == -1)
  543.                 *newStyles = AddDocTextStyle(dp, newStyle.textStyle);
  544.                 
  545.         }
  546.         
  547.         GXDisposeStyle(newStyle.textStyle);
  548.         
  549.         /* increment the reference count temporarily so that the new style does not get wiped out
  550.              if another new style is created */
  551.              
  552.         IncrementDocStyleRefCount(dp, *newStyles);
  553.                                     
  554.     }
  555.         
  556.     /* decrement the reference counts */
  557.  
  558.     newStyles -= numStyles;    
  559.     for(i=0; i< numStyles; i++, newStyles++)
  560.         DecrementDocStyleRefCount(dp, *newStyles);
  561.     
  562. }
  563.  
  564. void ModifyStyleTextFonts(DocPtr dp, short numFonts, gxFont * srcFonts, gxFont * dstFonts,
  565.                                 short numStyles, short * oldStyles, short * newStyles)
  566. {
  567.     short            i, j;
  568.     gxFont            font;
  569.     
  570.     if(numStyles == 0)
  571.         return;
  572.         
  573.     /* now loop through all of the given styles */
  574.  
  575.     for(i = 0; i < numStyles; i++, oldStyles++, newStyles++) {
  576.     
  577.         /* incase we don't match */
  578.     
  579.         *newStyles = *oldStyles;
  580.         
  581.         font = GetDocStyleTextFont(dp, *oldStyles);
  582.         
  583.         for(j=0; j<numFonts; j++)
  584.             if(srcFonts[j] == font)
  585.                 break;
  586.                 
  587.         if(j != numFonts)
  588.             *newStyles = SetDocStyleTextFont(dp,*oldStyles, dstFonts[j]);        /* in case we don't match */
  589.     
  590.         /* increment the reference count temporarily so that the new style does not get wiped out
  591.              if another new style is created */
  592.              
  593.         IncrementDocStyleRefCount(dp, *newStyles);
  594.                                     
  595.     }
  596.         
  597.     /* decrement the reference counts */
  598.  
  599.     newStyles -= numStyles;    
  600.     for(i=0; i< numStyles; i++, newStyles++)
  601.         DecrementDocStyleRefCount(dp, *newStyles);
  602.     
  603. }
  604.  
  605. void ModifyStyleTextSize(DocPtr dp, short textSize, short numStyles, short * oldStyles, short * newStyles)
  606. {
  607.     short            i;
  608.     
  609.     if(numStyles == 0)
  610.         return;
  611.         
  612.     /* now loop through all of the given styles */
  613.  
  614.     for(i = 0; i < numStyles; i++, oldStyles++, newStyles++) {
  615.     
  616.         *newStyles = SetDocStyleTextSize(dp,*oldStyles, textSize);        /* in case we don't match */
  617.     
  618.         /* increment the reference count temporarily so that the new style does not get wiped out
  619.              if another new style is created */
  620.              
  621.         IncrementDocStyleRefCount(dp, *newStyles);
  622.                                     
  623.     }
  624.         
  625.     /* decrement the reference counts */
  626.  
  627.     newStyles -= numStyles;    
  628.     for(i=0; i< numStyles; i++, newStyles++)
  629.         DecrementDocStyleRefCount(dp, *newStyles);
  630.     
  631. }
  632.  
  633. void UnionStyleFeatures(DocPtr dp, short numStyles, short *styles,
  634.                             gxFont fontId, short * numFeatureGroupsPtr,
  635.                             short *** featureGroupSizesPtr,
  636.                             gxRunFeature **** featureGroupsPtr)
  637. {
  638.     short            numFeatureGroups;
  639.     gxRunFeature    *** featureGroups;
  640.     short            ** featureGroupSizes;
  641.     short            numFeatures;
  642.     gxRunFeature    * features;
  643.     short            i, j, k, l;
  644.     
  645.     numFeatureGroups = 0;
  646.     featureGroups = (gxRunFeature ***) NewHandle(0);
  647.     featureGroupSizes = (short **) NewHandle(0);
  648.     
  649.     for(i=0; i<numStyles; i++, styles++) {
  650.     
  651.         if(GetDocStyleTextFont(dp, *styles) != fontId)
  652.             continue;
  653.             
  654.         /* get the feature group for the gxStyle */
  655.         
  656.         GetDocStyleFeatures(dp, *styles, &numFeatures, nil);
  657.         
  658.         features = (gxRunFeature *) NewPtr(sizeof(gxRunFeature) * numFeatures);
  659.         
  660.         GetDocStyleFeatures(dp, *styles, nil, features);
  661.         
  662.         /* try to find the feature set in our list of feature sets */
  663.         
  664.         for(j=0; j<numFeatureGroups; j++) {
  665.         
  666.             if((*featureGroupSizes)[j] != numFeatures)
  667.                 continue;
  668.                 
  669.             for(k=0; k<numFeatures; k++) {
  670.             
  671.                 for(l=0; l<numFeatures; l++)
  672.                     if(((*featureGroups)[j])[k].featureType == features[l].featureType &&
  673.                         ((*featureGroups)[j])[k].featureSelector == features[l].featureSelector)
  674.                         break;
  675.                 
  676.                 if(l == numFeatures)
  677.                     break;
  678.             }
  679.             
  680.             if(k == numFeatures)
  681.                 break;
  682.             
  683.         }
  684.         
  685.         /* if it was not found, then add to our group of feature sets */
  686.         
  687.         if(j == numFeatureGroups) {
  688.         
  689.             PtrAndHand((Ptr) &features, (Handle) featureGroups, sizeof(gxRunFeature *));
  690.             PtrAndHand((Ptr) &numFeatures, (Handle) featureGroupSizes, sizeof(short));
  691.             numFeatureGroups++;
  692.         
  693.         } else {
  694.         
  695.             DisposePtr((Ptr) features);
  696.             
  697.         }
  698.         
  699.     }
  700.  
  701.     *numFeatureGroupsPtr = numFeatureGroups;
  702.     *featureGroupSizesPtr = featureGroupSizes;
  703.     *featureGroupsPtr = featureGroups;
  704.  
  705. }
  706.  
  707. void UnionStyleVariations(DocPtr dp, short numStyles, short *styles,
  708.                         gxFont fontId, short * numInstancesPtr,
  709.                         short *** instanceSizesPtr, gxFontVariation **** instancesPtr)
  710. {
  711.     gxFontVariation    * variation;
  712.     short            numStyleVariations;
  713.     gxFontVariation    * styleVariations;
  714.     gxFontVariation    * styleVariation;
  715.     short            i, j, k;
  716.     short            * stylePtr;
  717.     StyleRec        aStyle;
  718.     short            numInstances;
  719.     gxFontVariation    *** instances, ** instance;
  720.     short            ** instanceSizes;
  721.         
  722.     numInstances = 0;
  723.     instances = (gxFontVariation ***) NewHandle(0);
  724.     instanceSizes = (short **) NewHandle(0);
  725.     
  726.     stylePtr = styles;
  727.     
  728.     for(i=0; i<numStyles; i++, stylePtr++) {
  729.     
  730.         aStyle = *GetDocStyle(dp, *stylePtr);
  731.         
  732.         if(aStyle.textFont != fontId)
  733.             continue;
  734.         
  735.         numStyleVariations = GXGetStyleFontVariations(aStyle.textStyle, nil);
  736.  
  737.         styleVariations = (gxFontVariation *) NewPtr((numStyleVariations) * sizeof(gxFontVariation));
  738.         
  739.         GXGetStyleFontVariations(aStyle.textStyle, styleVariations);
  740.         
  741.         
  742.         /* try to find this instance among the list of instances */
  743.         
  744.         instance = *instances;
  745.         
  746.         for(j=0; j<numInstances; j++, instance++) {
  747.         
  748.             if((*instanceSizes)[j] != numStyleVariations)
  749.                 continue;
  750.             
  751.             variation = *instance;
  752.             styleVariation = styleVariations;
  753.             
  754.             for(k=0; k<numStyleVariations; k++, variation++, styleVariation++)
  755.                 if(variation->name != styleVariation->name ||
  756.                    variation->value != styleVariation->value)
  757.                        break;
  758.                        
  759.             if(k != numStyleVariations)
  760.                 continue;
  761.                 
  762.             break;
  763.             
  764.         }
  765.         
  766.         if(j == numInstances) {
  767.         
  768.             PtrAndHand((Ptr) &styleVariations, (Handle) instances, sizeof(gxFontVariation *));
  769.             PtrAndHand((Ptr) &numStyleVariations, (Handle) instanceSizes, sizeof(short));
  770.             numInstances++;
  771.             
  772.         } else {
  773.                 
  774.             DisposePtr((Ptr) styleVariations);
  775.             
  776.         }
  777.         
  778.     }
  779.     
  780.     *numInstancesPtr = numInstances;
  781.     *instanceSizesPtr = instanceSizes;
  782.     *instancesPtr = instances;
  783.     
  784. }
  785.  
  786. void UnionStyleRunControls(DocPtr dp, short numStyles, short *styles,
  787.                                         gxRunControls * runControls, gxRunControls * runControlsMask)
  788. {
  789.     short            i;
  790.     short            * stylePtr;
  791.     char             * dst;
  792.     long            size;
  793.     gxRunControls        styleRunControls;
  794.     Boolean            firstTime;
  795.     StyleRec        aStyle;
  796.             
  797.     stylePtr = styles;
  798.     firstTime = true;
  799.     
  800.     for(i=0; i<numStyles; i++, stylePtr++) {
  801.     
  802.         aStyle = *GetDocStyle(dp, *stylePtr);
  803.         
  804.         if(!GXGetStyleRunControls(aStyle.textStyle, &styleRunControls)) {
  805.         
  806.             /* set the default values -- all zeros */
  807.             
  808.             size = sizeof(styleRunControls);
  809.             dst = (char *) &styleRunControls;
  810.             
  811.             while(size--)
  812.                 *dst++ = 0;
  813.         
  814.         }
  815.         
  816.         gxEditGetBitMaskOp(&styleRunControls, runControls, runControlsMask, 
  817.                                 sizeof(styleRunControls), firstTime);
  818.         
  819.         firstTime = false;
  820.     }
  821.     
  822.     /* fix up the mask */
  823.     
  824.     if(~runControlsMask->beforeWithStreamShift)
  825.         runControlsMask->beforeWithStreamShift = 0;
  826.  
  827.     if(~runControlsMask->afterWithStreamShift)
  828.         runControlsMask->afterWithStreamShift = 0;
  829.     
  830.     if(~runControlsMask->crossStreamShift)
  831.         runControlsMask->crossStreamShift = 0;
  832.         
  833.     if(~runControlsMask->imposedWidth)
  834.         runControlsMask->imposedWidth = 0;
  835.         
  836.     if(~runControlsMask->track)
  837.         runControlsMask->track = 0;
  838.         
  839.     if(~runControlsMask->hangingInhibitFactor)
  840.         runControlsMask->hangingInhibitFactor = 0;
  841.         
  842.     if(~runControlsMask->kerningInhibitFactor)
  843.         runControlsMask->kerningInhibitFactor = 0;
  844.     
  845.     if(~runControlsMask->decompositionAdjustmentFactor)
  846.         runControlsMask->decompositionAdjustmentFactor = 0;
  847.         
  848.     if(~runControlsMask->baselineType)
  849.         runControlsMask->baselineType = 0;
  850.         
  851. }
  852.  
  853. void UnionFontRunControls(DocPtr dp, short numStyles, short *styles, gxFont fontId,
  854.                                     gxRunControls * runControls, gxRunControls * runControlsMask)
  855. {
  856.     short            i;
  857.     short            * stylePtr;
  858.     char             * dst;
  859.     long            size;
  860.     gxRunControls        styleRunControls;
  861.     Boolean            firstTime;
  862.     StyleRec        aStyle;
  863.             
  864.     stylePtr = styles;
  865.     firstTime = true;
  866.     
  867.     for(i=0; i<numStyles; i++, stylePtr++) {
  868.     
  869.         if(GetDocStyleTextFont(dp, *stylePtr) != fontId)
  870.             continue;
  871.             
  872.         aStyle = *GetDocStyle(dp, *stylePtr);
  873.         
  874.         if(!GXGetStyleRunControls(aStyle.textStyle, &styleRunControls)) {
  875.         
  876.             /* set the default values -- all zeros */
  877.             
  878.             size = sizeof(styleRunControls);
  879.             dst = (char *) &styleRunControls;
  880.             
  881.             while(size--)
  882.                 *dst++ = 0;
  883.         
  884.         }
  885.         
  886.         gxEditGetBitMaskOp(&styleRunControls, runControls, runControlsMask, 
  887.                                 sizeof(styleRunControls), firstTime);
  888.         
  889.         firstTime = false;
  890.     }
  891.     
  892.     /* fix up the mask */
  893.     
  894.     if(~runControlsMask->beforeWithStreamShift)
  895.         runControlsMask->beforeWithStreamShift = 0;
  896.  
  897.     if(~runControlsMask->afterWithStreamShift)
  898.         runControlsMask->afterWithStreamShift = 0;
  899.     
  900.     if(~runControlsMask->crossStreamShift)
  901.         runControlsMask->crossStreamShift = 0;
  902.         
  903.     if(~runControlsMask->imposedWidth)
  904.         runControlsMask->imposedWidth = 0;
  905.         
  906.     if(~runControlsMask->track)
  907.         runControlsMask->track = 0;
  908.         
  909.     if(~runControlsMask->hangingInhibitFactor)
  910.         runControlsMask->hangingInhibitFactor = 0;
  911.         
  912.     if(~runControlsMask->kerningInhibitFactor)
  913.         runControlsMask->kerningInhibitFactor = 0;
  914.     
  915.     if(~runControlsMask->decompositionAdjustmentFactor)
  916.         runControlsMask->decompositionAdjustmentFactor = 0;
  917.         
  918.     if(~runControlsMask->baselineType)
  919.         runControlsMask->baselineType = 0;
  920.         
  921. }
  922.